
#include <stdio.h>
#include <os/armxdsp.h>

#include "hs_types.h"
#include "mac_debug.h"
#include "wlan_const.h"
#include "hw_rx_list.h"
#include "wlan_types.h"
#include "wlan_mgt.h"

#include "sb3xdef.h"
#include "memtest.h"
#include "wlan_mac.h"

volatile int armxdsp_control_slot = ARMXDSP_CONTROL_SLOT ;
volatile int dsp2arm_event_slot   = DSP2ARM_EVENT_SLOT ;
volatile int arm2dsp_data_slot    = ARM2DSP_DATA_SLOT ;
volatile int dsp2arm_data_slot    = DSP2ARM_DATA_SLOT ;

volatile int gArmQEnabled = 0 ;

void dump_mem(char *name, unsigned char *data, int len)
{
    unsigned int i =  0 ;

    printf("\n--------------\nMem dump for %s (size %u):\n%08x  ", name, len, i) ;

    if (len > 0)
    {
        for (i = 0 ; i < len ; ++i)
        {

            printf("%02x ", data[i]) ;

            if (i > 0 && ((i+1)%0x10 == 0))
            {
                printf("\n%08x  ", i+1) ;
            }
        }
    }

    printf("\n===============\n") ;
}

int send_data_to_arm(unsigned char *data, unsigned short data_len)
{
    int status;
    armxdsp_sender_t s;

    if (!gArmQEnabled)
    {

        return 0 ;

    }

    status = armxdsp_send_begin_nb(&s, MAC_DSP_CORE, dsp2arm_data_slot, data_len);
    if (status < 0)
    {
        ERRORDEBUG(sprintf(error_logmsg,"send_data_to_arm: cannot begin send %d\n", status)) ;

        return status;
    }

    memcpy(s.data, data, data_len);

    armxdsp_send_end(&s);

    MACDEBUG(sprintf(mac_logmsg,
                     "send_data_to_arm: sent message slot = %d, size = %d, type = %04x\n",
                     s.slot, s.size, *((char *)s.data+12) << 8 | *((char *)s.data+13)));

    return 0;
}

int receive_data_from_arm(unsigned char *rx_data, unsigned short *rx_data_len)
{
    int status;
    armxdsp_receiver_t r;

    if (!gArmQEnabled)
    {

        *rx_data_len = 0 ;

        return -1 ;
    }

    if (rx_data == NULL || rx_data_len == NULL)
    {
        ERRORDEBUG(sprintf(error_logmsg,"receive_data_from_arm: one parameter is a NULL ptr %p %p\n", rx_data, rx_data_len));
    }

    status = armxdsp_receive_begin_nb(&r, MAC_DSP_CORE, 0x1 << arm2dsp_data_slot);

    if (status != 0)
    {
        *rx_data_len = 0 ;

        if (status != ARMXDSP_EAGAIN)
        {
            ERRORDEBUG(sprintf(error_logmsg,"receive_data_from_arm: cannot begin receive %d\n", status));
        }

        return status;
    }

    if (r.size > *rx_data_len)
    {
        *rx_data_len = 0 ;

        ERRORDEBUG(sprintf(error_logmsg,"receive_data_from_arm: received frame is bigger than buffer (%u)\n", r.size));

        armxdsp_receive_end(&r);

        return -1 ;
    }

    *rx_data_len=r.size;

    memcpy(rx_data, r.data, *rx_data_len);

    armxdsp_receive_end(&r);

    MACDEBUG(sprintf(mac_logmsg,
                     "receive_data_from_arm: received message slot = %d, size = %d, type = %04x\n",
                     r.slot, r.size, *((char *)r.data+12) << 8 | *((char *)r.data+13)));

    return 0;
}

int receive_ctrl_from_arm(uint32_t *req, uint8_t *data, uint32_t *len)
{
    int status=0;
    armxdsp_receiver_t r;

    if (!gArmQEnabled)
    {
        *len = 0 ;

        return -1 ;
    }

    status = armxdsp_receive_begin_nb(&r, MAC_DSP_CORE, 0x1 << armxdsp_control_slot);
    if (status == ARMXDSP_EAGAIN)
    {
        //MACDEBUG(sprintf(mac_logmsg,"receive_ctrl_from_arm: there is nothing in the queue\n"));

        return status;
    }
    else if (status != 0)
    {
        ERRORDEBUG(sprintf(error_logmsg,"receive_ctrl_from_arm: cannot begin receive %d\n", status));

        return status;
    }

    //dump_mem("receive_ctrl_from_arm - r.data", r.data, r.size) ;

    if (r.size < sizeof(uint32_t))
    {
        *len = 0 ;

        ERRORDEBUG(sprintf(error_logmsg,"receive_ctrl_from_arm: msg length is too small\n")) ;

        armxdsp_receive_end(&r);

        return -1 ;
    }

    if ( (r.size - sizeof(uint32_t)) > *len)
    {
        *len = 0 ;

        ERRORDEBUG(sprintf(error_logmsg,"receive_ctrl_from_arm: rx buffer length is too small\n")) ;

        armxdsp_receive_end(&r);

        return -1 ;
    }

    *req = ((int32_t *)r.data)[0] ;

    *len = r.size - sizeof(uint32_t) ;

    memcpy(data, (uint8_t *)r.data + 4, *len) ;

    armxdsp_receive_end(&r);

    MACDEBUG(sprintf(mac_logmsg,"receive_ctrl_from_arm: received message slot = %d, req %x size = %d, data = %p\n", r.slot, req, r.size, r.data));

    return 0 ;
}

int send_ctrl_to_arm(int32_t res, uint8_t *data, uint32_t len)
{
    int status=0;
    armxdsp_sender_t s;

    if (!gArmQEnabled)
    {

        return 0 ;

    }

    if (data == NULL)
    {
        /* ignore len */
        len = 0 ;
    }

    status = armxdsp_send_begin_nb(&s, MAC_DSP_CORE, armxdsp_control_slot, sizeof(uint32_t) + len);
    if (status < 0)
    {
        ERRORDEBUG(sprintf(error_logmsg,"send_ctrl_to_arm: cannot begin send %d\n", status)) ;

        return status;
    }

    ((int32_t *)(s.data))[0] = res ;

    if (data != NULL)
    {
        memcpy((char *)(s.data) + sizeof(uint32_t), data, len) ;
    }

    armxdsp_send_end(&s);

    MACDEBUG(sprintf(mac_logmsg,"send_ctrl_to_arm: sent message slot = %d, resp %d size = %d, data = %p\n", s.slot, res, s.size, s.data));

    return 0 ;
}

int send_event_to_arm(uint32_t event, uint8_t *data, uint32_t len)
{
    int status=0;
    armxdsp_sender_t s;

    if (!gArmQEnabled)
    {

        return 0 ;

    }

    if (data == NULL)
    {
        /* ignore len */
        len = 0 ;
    }

    status = armxdsp_send_begin_nb(&s, MAC_DSP_CORE, dsp2arm_event_slot, sizeof(uint32_t) + len);
    if (status < 0)
    {
        ERRORDEBUG(sprintf(error_logmsg,"send_event_to_arm: cannot begin send %d\n", status)) ;

        return status;
    }

    ((int32_t *)(s.data))[0] = event ;

    if (data != NULL)
    {
        memcpy((char *)(s.data) + sizeof(uint32_t), data, len) ;
    }

    armxdsp_send_end(&s);

    MACDEBUG(sprintf(mac_logmsg,"send_event_to_arm: sent message slot = %d, event %x size = %d, data = %p\n", s.slot, event, s.size, s.data));

    return 0 ;
}

int init_mac_to_appl()
{
    int status ;

    gArmQEnabled = 0 ;

    if (!mac_config_g.llc_disabled)
    {
        status = armxdsp_open_queues();
        if (status == 0)
        {

            gArmQEnabled = 1 ;
        }
        else
        {
            printf("\nERROR: couldn't open ARM/DSP mailbox queues: %d\n", status);

            gArmQEnabled = 0 ;
            mac_config_g.llc_disabled = 1 ;
        }
    }

    if (mac_config_g.llc_disabled)
    {
        printf("\nINFO: ARM/DSP mailboxes are disabled.\n\n") ;

        return -1;
    }

    return 0 ;
}
